package com.cartel.genius.services.impl;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.cartel.genius.dao.PlaceDAO;
import com.cartel.genius.dao.exceptions.CategoryNotFoundException;
import com.cartel.genius.dao.exceptions.PlaceExistsException;
import com.cartel.genius.dao.exceptions.PlaceNotFoundException;
import com.cartel.genius.dao.exceptions.PlaceParentNotFoundException;
import com.cartel.genius.dto.CategoryTO;
import com.cartel.genius.dto.PlaceTO;
import com.cartel.genius.services.PlaceService;
import com.mysql.jdbc.StringUtils;

/**
 * Service class for Place operations
 * 
 * @author Naresh Reddy
 */
public class PlaceServiceImpl implements PlaceService {
	
	private static final Logger logger = LoggerFactory.getLogger(PlaceServiceImpl.class);
	
	private PlaceDAO placeDAO = null;	
	
	public void setPlaceDAO(PlaceDAO placeDAO) {
		this.placeDAO = placeDAO;
	}

	/**
	 * Method to add root place. All other places will be childs of this place
	 * 
	 * @param placeCode
	 * @param placeName
	 * @param categoryName
	 * @return PlaceTO
	 * @throws PlaceExistsException
	 * @throws CategoryNotFoundException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public PlaceTO addRootPlace(String placeCode, String placeName, String categoryName) throws PlaceExistsException, CategoryNotFoundException {
		logger.debug("Entering [addRootPlace] of [PlaceServiceImpl]");
		if (StringUtils.isNullOrEmpty(placeCode) || StringUtils.isNullOrEmpty(placeName) || StringUtils.isNullOrEmpty(categoryName)) {
			logger.warn("Illegal arguments to addRootPlace method : " + "placeCode : " + placeCode + " : placeName : " + placeName + " : categoryName : " + categoryName);
			throw new IllegalArgumentException("Invalid arguments to add root place");
		}
		
		PlaceTO placeTO = new PlaceTO();
		placeTO.setPlaceCode(placeCode);
		placeTO.setPlaceName(placeName);
		
		CategoryTO categoryTO = new CategoryTO();
		categoryTO.setCategoryName(categoryName);
		
		placeTO.setCategoryTO(categoryTO);
		
		PlaceTO rootPlace = placeDAO.addRootPlace(placeTO);
		logger.debug("Exiting [addRootPlace] of [PlaceServiceImpl]");
		
		return rootPlace;
	}
	
	/**
	 * Method to add root place. All other places will be childs of this place
	 * 
	 * @param placeCode
	 * @param placeName
	 * @param categoryId
	 * @return PlaceTO
	 * @throws PlaceExistsException
	 * @throws CategoryNotFoundException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public PlaceTO addRootPlace(String placeCode, String placeName, int categoryId) throws PlaceExistsException, CategoryNotFoundException {
		logger.debug("Entering [addRootPlace] of [PlaceServiceImpl]");
		if (StringUtils.isNullOrEmpty(placeCode) || StringUtils.isNullOrEmpty(placeName) || categoryId == 0) {
			logger.warn("Illegal arguments to addRootPlace method : " + "placeCode : " + placeCode + " : placeName : " + placeName + " : categoryId : " + categoryId);
			throw new IllegalArgumentException("Invalid arguments to add root place");
		}
		
		PlaceTO placeTO = new PlaceTO();
		placeTO.setPlaceCode(placeCode);
		placeTO.setPlaceName(placeName);
		
		CategoryTO categoryTO = new CategoryTO();
		categoryTO.setCategoryId(categoryId);
		
		placeTO.setCategoryTO(categoryTO);
		
		PlaceTO rootPlace = placeDAO.addRootPlace(placeTO);
		logger.debug("Exiting [addRootPlace] of [PlaceServiceImpl]");
		
		return rootPlace;
	}	
	/**
	 * Method to add root place. All other places will be childs of this place
	 * 
	 * @param placeTO
	 * @return PlaceTO
	 * @throws PlaceExistsException
	 * @throws CategoryNotFoundException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public PlaceTO addRootPlace(PlaceTO placeTO) throws PlaceExistsException, CategoryNotFoundException {
		logger.debug("Entering [addRootPlace] of [PlaceServiceImpl]");
		if (placeTO == null || StringUtils.isNullOrEmpty(placeTO.getPlaceCode()) || StringUtils.isNullOrEmpty(placeTO.getPlaceName()) || (placeTO.getCategoryTO() == null) || (placeTO.getCategoryTO().getCategoryId() == 0 && StringUtils.isNullOrEmpty(placeTO.getCategoryTO().getCategoryName()))) {
			logger.warn("Illegal arguments to addRootPlace method : " + "placeCode : " + placeTO.getPlaceCode() + " : placeName : " + placeTO.getPlaceName() + " : categoryTO : " + placeTO.getCategoryTO());
			throw new IllegalArgumentException("Invalid arguments to add root place");
		}
		
		PlaceTO rootPlace = placeDAO.addRootPlace(placeTO);
		logger.debug("Exiting [addRootPlace] of [PlaceServiceImpl]");
		
		return rootPlace;
	}
	
	/**
	 * Method to add a place
	 * 
	 * @param placeTO
	 * @return PlaceTO
	 * @throws PlaceExistsException
	 * @throws PlaceParentNotFoundException
	 * @throws CategoryNotFoundException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public PlaceTO addPlace(PlaceTO placeTO) throws PlaceExistsException, PlaceParentNotFoundException, CategoryNotFoundException {
		
		logger.debug("Exiting [addPlace] of [PlaceServiceImpl]");
		
		if (placeTO == null || (StringUtils.isNullOrEmpty(placeTO.getParentPlaceCode()) && placeTO.getParentPlaceId() == 0) || placeTO.getCategoryTO() == null || (placeTO.getCategoryTO().getCategoryId() == 0 && StringUtils.isNullOrEmpty(placeTO.getCategoryTO().getCategoryName()))) {
			logger.warn("Invalid data for adding a place");
			throw new IllegalArgumentException("Invalid data for adding a place");
		}
		
		PlaceTO addedPlace = placeDAO.addPlace(placeTO);
		
		logger.debug("Exiting [addPlace] of [PlaceServiceImpl]");
		
		return addedPlace;
	}
	
	/**
	 * Method to add list of places
	 * 
	 * @param placeTOList
	 * @return List<PlaceTO>
	 * @throws PlaceExistsException
	 * @throws PlaceParentNotFoundException
	 * @throws CategoryNotFoundException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public List<PlaceTO> addPlaces(List<PlaceTO> placeTOList) {
		logger.debug("Entered [addPlaces] of [PlaceServiceImpl]");
		
		if (placeTOList == null || placeTOList.size() == 0) {
			logger.warn("Places list is either null or empty");
			throw new IllegalArgumentException("Places list is either null or empty");
		}
		
		List<PlaceTO> addedPlaces = new ArrayList<PlaceTO>();
		PlaceTO addedPlace = null;
		for (PlaceTO placeTO : placeTOList) {
			try {
				addedPlace = addPlace(placeTO);				
			} catch (PlaceExistsException e) {
				logger.warn(e.getMessage());
				continue;
			} catch (PlaceParentNotFoundException e) {
				logger.warn(e.getMessage());
				continue;
			} catch (CategoryNotFoundException e) {
				logger.warn(e.getMessage());
				continue;
			}
			
			addedPlaces.add(addedPlace);
		}
		
		return addedPlaces;
	}
	
	/**
	 * Method to add list of places under a parent place. It is adviceable to use this API when you want to add places 
	 * under a single parent. In this case this method will be more efficient.
	 * 
	 * @param placeTOList
	 * @return List<PlaceTO>
	 * @throws PlaceExistsException
	 * @throws PlaceParentNotFoundException
	 * @throws CategoryNotFoundException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public List<PlaceTO> addPlaces(List<PlaceTO> placeTOList, PlaceTO parentPlace) throws PlaceParentNotFoundException, CategoryNotFoundException {
		logger.debug("Entered [addPlaces] of [PlaceServiceImpl]");
		
		if(placeTOList == null || placeTOList.size() == 0) {
			logger.warn("Places list is either null or empty");
			throw new IllegalArgumentException("Places list is either null or empty");
		}
		
		if (parentPlace == null || (parentPlace.getPlaceId() == 0 && StringUtils.isNullOrEmpty(parentPlace.getPlaceCode()))) {
			logger.warn("Illegal parent place information");
			throw new IllegalArgumentException("Illegal parent place information");
		}
		return placeDAO.addPlaces(placeTOList, parentPlace);
	}
	
	/**
	 * Method to add place
	 * 
	 * @param placeName
	 * @param placeCode
	 * @param parentPlaceId
	 * @param categoryId
	 * @return PlaceTO
	 * @throws PlaceExistsException
	 * @throws PlaceParentNotFoundException
	 * @throws CategoryNotFoundException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public PlaceTO addPlace(String placeName, String placeCode, int parentPlaceId, int categoryId) throws PlaceExistsException, PlaceParentNotFoundException, CategoryNotFoundException {
		logger.debug("Entered [addPlace] of [PlaceServiceImpl]");
		
		if (StringUtils.isNullOrEmpty(placeName) || StringUtils.isNullOrEmpty(placeCode) || parentPlaceId == 0 || categoryId == 0) {
			logger.warn("Illegal arguments for adding a place");
			throw new IllegalArgumentException("Illegal arguments for adding a place");
		}
		
		PlaceTO placeTO = new PlaceTO();
		placeTO.setPlaceName(placeName);
		placeTO.setPlaceCode(placeCode);
		placeTO.setParentPlaceId(parentPlaceId);
		
		CategoryTO categoryTO = new CategoryTO();
		categoryTO.setCategoryId(categoryId);
		placeTO.setCategoryTO(categoryTO);
		
		return addPlace(placeTO);
	}
	
	/**
	 * Method to add a place
	 * 
	 * @param placeName
	 * @param placeCode
	 * @param parentPlaceCode
	 * @param categoryId
	 * @return PlaceTO
	 * @throws PlaceExistsException
	 * @throws PlaceParentNotFoundException
	 * @throws CategoryNotFoundException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public PlaceTO addPlace(String placeName, String placeCode, String parentPlaceCode, int categoryId) throws PlaceExistsException, PlaceParentNotFoundException, CategoryNotFoundException {
		logger.debug("Entered [addPlace] of [PlaceServiceImpl]");
		
		if (StringUtils.isNullOrEmpty(placeName) || StringUtils.isNullOrEmpty(placeCode) || StringUtils.isNullOrEmpty(parentPlaceCode) || categoryId == 0) {
			logger.warn("Illegal arguments for adding a place");
			throw new IllegalArgumentException("Illegal arguments for adding a place");
		}
		
		PlaceTO placeTO = new PlaceTO();
		placeTO.setPlaceName(placeName);
		placeTO.setPlaceCode(placeCode);
		placeTO.setParentPlaceCode(parentPlaceCode);
		
		CategoryTO categoryTO = new CategoryTO();
		categoryTO.setCategoryId(categoryId);
		placeTO.setCategoryTO(categoryTO);
		
		return addPlace(placeTO);
	}
	
	/**
	 * Method to add a place
	 * 
	 * @param placeName
	 * @param placeCode
	 * @param parentPlaceId
	 * @param categoryName
	 * @return PlaceTO
	 * @throws PlaceExistsException
	 * @throws PlaceParentNotFoundException
	 * @throws CategoryNotFoundException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public PlaceTO addPlace(String placeName, String placeCode, int parentPlaceId, String categoryName) throws PlaceExistsException, PlaceParentNotFoundException, CategoryNotFoundException {
		logger.debug("Entered [addPlace] of [PlaceServiceImpl]");
		
		if (StringUtils.isNullOrEmpty(placeName) || StringUtils.isNullOrEmpty(placeCode) || parentPlaceId == 0 || StringUtils.isNullOrEmpty(categoryName)) {
			logger.warn("Illegal arguments for adding a place");
			throw new IllegalArgumentException("Illegal arguments for adding a place");
		}
		
		PlaceTO placeTO = new PlaceTO();
		placeTO.setPlaceName(placeName);
		placeTO.setPlaceCode(placeCode);
		placeTO.setParentPlaceId(parentPlaceId);
		
		CategoryTO categoryTO = new CategoryTO();
		categoryTO.setCategoryName(categoryName);
		placeTO.setCategoryTO(categoryTO);
		
		return addPlace(placeTO);
	}
	
	/**
	 * Method to add a place
	 * 
	 * @param placeName
	 * @param placeCode
	 * @param parentPlaceCode
	 * @param categoryName
	 * @return PlaceTO
	 * @throws PlaceExistsException
	 * @throws PlaceParentNotFoundException
	 * @throws CategoryNotFoundException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public PlaceTO addPlace(String placeName, String placeCode, String parentPlaceCode, String categoryName) throws PlaceExistsException, PlaceParentNotFoundException, CategoryNotFoundException {
		logger.debug("Entered [addPlace] of [PlaceServiceImpl]");
		
		if (StringUtils.isNullOrEmpty(placeName) || StringUtils.isNullOrEmpty(placeCode) || StringUtils.isNullOrEmpty(parentPlaceCode) || StringUtils.isNullOrEmpty(categoryName)) {
			logger.warn("Illegal arguments for adding a place");
			throw new IllegalArgumentException("Illegal arguments for adding a place");
		}
		
		PlaceTO placeTO = new PlaceTO();
		placeTO.setPlaceName(placeName);
		placeTO.setPlaceCode(placeCode);
		placeTO.setParentPlaceCode(parentPlaceCode);
		
		CategoryTO categoryTO = new CategoryTO();
		categoryTO.setCategoryName(categoryName);
		placeTO.setCategoryTO(categoryTO);
		
		return addPlace(placeTO);
	}
	
	/**
	 * Method to modify a place name
	 * 
	 * @param placeId
	 * @param oldPlaceName
	 * @param newPlaceName
	 * @return
	 * @throws PlaceExistsException
	 * @throws PlaceNotFoundException
	 * @throws CategoryNotFoundException 
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public PlaceTO modifyPlaceName(int placeId, String newPlaceName) throws PlaceExistsException, PlaceNotFoundException, CategoryNotFoundException {
		logger.debug("Entered [modifyPlaceName] of [PlaceServiceImpl]");
		
		if (placeId == 0 || StringUtils.isNullOrEmpty(newPlaceName)) {
			logger.warn("Illegal data for changing place name");
			throw new IllegalArgumentException("Illegal data for changing place name");
		}
		
		PlaceTO oldPlace = new PlaceTO();
		PlaceTO newPlace = new PlaceTO();
		
		oldPlace.setPlaceId(placeId);		
		newPlace.setPlaceName(newPlaceName);
		
		PlaceTO modifiedPlace = placeDAO.modifyPlace(oldPlace, newPlace);
		
		logger.debug("Exiting [modifyPlaceName] of [PlaceServiceImpl]");
		
		return modifiedPlace;
	}
	
	/**
	 * Method to modify a place name
	 * 
	 * @param placeCode
	 * @param oldPlaceName
	 * @param newPlaceName
	 * @return PlaceTO
	 * @throws PlaceExistsException
	 * @throws PlaceNotFoundException
	 * @throws CategoryNotFoundException 
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public PlaceTO modifyPlaceName(String placeCode, String newPlaceName) throws PlaceExistsException, PlaceNotFoundException, CategoryNotFoundException { 
		logger.debug("Entered [modifyPlaceName] of [PlaceServiceImpl]");
		
		if (StringUtils.isNullOrEmpty(placeCode) || StringUtils.isNullOrEmpty(newPlaceName)) {
			logger.warn("Illegal data for changing place name");
			throw new IllegalArgumentException("Illegal data for changing place name");
		}
		
		PlaceTO oldPlace = new PlaceTO();
		PlaceTO newPlace = new PlaceTO();
		
		oldPlace.setPlaceCode(placeCode);		
		newPlace.setPlaceName(newPlaceName);
		
		PlaceTO modifiedPlace = placeDAO.modifyPlace(oldPlace, newPlace);
		
		logger.debug("Exiting [modifyPlaceName] of [PlaceServiceImpl]");
		
		return modifiedPlace;
	}
	
	/**
	 * Method to modify a place code
	 * 
	 * @param oldPlaceCode
	 * @param newPlaceCode
	 * @return PlaceTO
	 * @throws PlaceExistsException
	 * @throws PlaceNotFoundException
	 * @throws CategoryNotFoundException 
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public PlaceTO modifyPlaceCode(String oldPlaceCode, String newPlaceCode) throws PlaceExistsException, PlaceNotFoundException, CategoryNotFoundException {
		logger.debug("Entered [modifyPlaceCode] of [PlaceServiceImpl]");
		
		if (StringUtils.isNullOrEmpty(oldPlaceCode) || StringUtils.isNullOrEmpty(newPlaceCode)) {
			logger.warn("Illegal data for changing place code");
			throw new IllegalArgumentException("Illegal data for changing place code");
		}
		
		PlaceTO oldPlace = new PlaceTO();
		PlaceTO newPlace = new PlaceTO();
		
		oldPlace.setPlaceCode(oldPlaceCode);		
		newPlace.setPlaceCode(newPlaceCode);
		
		PlaceTO modifiedPlace = placeDAO.modifyPlace(oldPlace, newPlace);
		
		logger.debug("Exiting [modifyPlaceCode] of [PlaceServiceImpl]");
		
		return modifiedPlace;
	}
	
	/**
	 * Method to modify a place which includes place name, place code, place parent
	 * 
	 * @param placeId
	 * @param newPlace
	 * @return PlaceTO
	 * @throws PlaceExistsException
	 * @throws PlaceNotFoundException
	 * @throws CategoryNotFoundException;
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public PlaceTO modifyPlace(int placeId, PlaceTO newPlace) throws PlaceExistsException, PlaceNotFoundException, CategoryNotFoundException {
		logger.debug("Entered [modifyPlace] of [PlaceServiceImpl]");
		
		if (placeId == 0 || newPlace == null) {
			logger.warn("Illegal data for changing place");
			throw new IllegalArgumentException("Illegal data for changing place");
		}
		
		PlaceTO oldPlace = new PlaceTO();		
		oldPlace.setPlaceId(placeId);		
		
		PlaceTO modifiedPlace = placeDAO.modifyPlace(oldPlace, newPlace);		
		logger.debug("Exiting [modifyPlaceCode] of [PlaceServiceImpl]");
		
		return modifiedPlace;
	}
	
	/**
	 * Method to modify a place which includes place name, place code, place parent and place category
	 * 
	 * @param placeCode
	 * @param newPlace
	 * @return PlaceTO
	 * @throws PlaceExistsException
	 * @throws PlaceNotFoundException
	 * @throws CategoryNotFoundException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public PlaceTO modifyPlace(String placeCode, PlaceTO newPlace) throws PlaceExistsException, PlaceNotFoundException, CategoryNotFoundException {
		logger.debug("Entered [modifyPlace] of [PlaceServiceImpl]");
		
		if (StringUtils.isNullOrEmpty(placeCode) || newPlace == null) {
			logger.warn("Illegal data for changing place");
			throw new IllegalArgumentException("Illegal data for changing place");
		}
		
		PlaceTO oldPlace = new PlaceTO();		
		oldPlace.setPlaceCode(placeCode);		
		
		PlaceTO modifiedPlace = placeDAO.modifyPlace(oldPlace, newPlace);		
		logger.debug("Exiting [modifyPlaceCode] of [PlaceServiceImpl]");
		
		return modifiedPlace;
	}
	
	/**
	 * Method to modify a place which includes place name, place code, place parent and place category
	 * 
	 * @param oldPlace
	 * @param newPlace
	 * @return PlaceTO
	 * @throws PlaceExistsException
	 * @throws PlaceNotFoundException
	 * @throws CategoryNotFoundException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public PlaceTO modifyPlace(PlaceTO oldPlace, PlaceTO newPlace) throws PlaceExistsException, PlaceNotFoundException, CategoryNotFoundException {
		logger.debug("Entered [modifyPlace] of [PlaceServiceImpl]");
		
		if (oldPlace == null || newPlace == null) {
			logger.warn("Illegal data for changing place");
			throw new IllegalArgumentException("Illegal data for changing place");
		}
		
		PlaceTO modifiedPlace = placeDAO.modifyPlace(oldPlace, newPlace);		
		logger.debug("Exiting [modifyPlace] of [PlaceServiceImpl]");
		
		return modifiedPlace;
	}
	
	/**
	 * Method to modify a place category
	 * 
	 * @param placeId
	 * @param newCategoryId
	 * @return PlaceTO
	 * @throws PlaceNotFoundException
	 * @throws CategoryNotFoundException
	 * @throws PlaceExistsException 
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public PlaceTO modifyPlaceCategory(int placeId, int newCategoryId) throws PlaceNotFoundException, CategoryNotFoundException, PlaceExistsException {
		logger.debug("Entered [modifyPlaceCategory] of [PlaceServiceImpl]");
		
		if (placeId == 0 || newCategoryId == 0) {
			logger.warn("Illegal data for changing place category");
			throw new IllegalArgumentException("Illegal data for changing place category");
		}
		
		PlaceTO oldPlace = new PlaceTO();
		PlaceTO newPlace = new PlaceTO();
		
		oldPlace.setPlaceId(placeId);		
		
		CategoryTO newCategory = new CategoryTO();
		newCategory.setCategoryId(newCategoryId);
		newPlace.setCategoryTO(newCategory);
		
		PlaceTO modifiedPlace = placeDAO.modifyPlace(oldPlace, newPlace);
		
		logger.debug("Exiting [modifyPlaceCategory] of [PlaceServiceImpl]");
		
		return modifiedPlace;
	}
	
	/**
	 * Method to modify a place category
	 * 
	 * @param placeCode
	 * @param newCategoryId
	 * @return PlaceTO
	 * @throws PlaceNotFoundException
	 * @throws CategoryNotFoundException
	 * @throws PlaceExistsException 
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public PlaceTO modifyPlaceCategory(String placeCode, int newCategoryId) throws PlaceNotFoundException, CategoryNotFoundException, PlaceExistsException {
		logger.debug("Entered [modifyPlaceCategory] of [PlaceServiceImpl]");
		
		if (StringUtils.isNullOrEmpty(placeCode) || newCategoryId == 0) {
			logger.warn("Illegal data for changing place category");
			throw new IllegalArgumentException("Illegal data for changing place category");
		}
		
		PlaceTO oldPlace = new PlaceTO();
		PlaceTO newPlace = new PlaceTO();
		
		oldPlace.setPlaceCode(placeCode);		
		
		CategoryTO newCategory = new CategoryTO();
		newCategory.setCategoryId(newCategoryId);
		newPlace.setCategoryTO(newCategory);
		
		PlaceTO modifiedPlace = placeDAO.modifyPlace(oldPlace, newPlace);
		
		logger.debug("Exiting [modifyPlaceCategory] of [PlaceServiceImpl]");
		
		return modifiedPlace;
	}
	
	/**
	 * Method to modify a place category
	 * 
	 * @param placeId
	 * @param categoryName
	 * @return PlaceTO
	 * @throws PlaceNotFoundException
	 * @throws CategoryNotFoundException
	 * @throws PlaceExistsException 
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public PlaceTO modifyPlaceCategory(int placeId, String categoryName) throws PlaceNotFoundException, CategoryNotFoundException, PlaceExistsException {
		logger.debug("Entered [modifyPlaceCategory] of [PlaceServiceImpl]");
		
		if (placeId == 0 || StringUtils.isNullOrEmpty(categoryName)) {
			logger.warn("Illegal data for changing place category");
			throw new IllegalArgumentException("Illegal data for changing place category");
		}
		
		PlaceTO oldPlace = new PlaceTO();
		PlaceTO newPlace = new PlaceTO();
		
		oldPlace.setPlaceId(placeId);		
		
		CategoryTO newCategory = new CategoryTO();
		newCategory.setCategoryName(categoryName);
		newPlace.setCategoryTO(newCategory);
		
		PlaceTO modifiedPlace = placeDAO.modifyPlace(oldPlace, newPlace);
		
		logger.debug("Exiting [modifyPlaceCategory] of [PlaceServiceImpl]");
		
		return modifiedPlace;
	}
	
	/**
	 * Method to modify a place category
	 * 
	 * @param placeCode
	 * @param categoryName
	 * @return PlaceTO
	 * @throws PlaceNotFoundException
	 * @throws CategoryNotFoundException
	 * @throws PlaceExistsException 
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public PlaceTO modifyPlaceCategory(String placeCode, String categoryName) throws PlaceNotFoundException, CategoryNotFoundException, PlaceExistsException {
		logger.debug("Entered [modifyPlaceCategory] of [PlaceServiceImpl]");
		
		if (StringUtils.isNullOrEmpty(placeCode) || StringUtils.isNullOrEmpty(categoryName)) {
			logger.warn("Illegal data for changing place category");
			throw new IllegalArgumentException("Illegal data for changing place category");
		}
		
		PlaceTO oldPlace = new PlaceTO();
		PlaceTO newPlace = new PlaceTO();
		
		oldPlace.setPlaceCode(placeCode);		
		
		CategoryTO newCategory = new CategoryTO();
		newCategory.setCategoryName(categoryName);
		newPlace.setCategoryTO(newCategory);
		
		PlaceTO modifiedPlace = placeDAO.modifyPlace(oldPlace, newPlace);
		
		logger.debug("Exiting [modifyPlaceCategory] of [PlaceServiceImpl]");
		
		return modifiedPlace;
	}
	
	/**
	 * Method to modify a place parent
	 * 
	 * @param placeId
	 * @param parentPlaceId
	 * @return PlaceTO
	 * @throws PlaceNotFoundException
	 * @throws PlaceParentNotFoundException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public PlaceTO modifyPlaceParent(int placeId, int parentPlaceId) throws PlaceNotFoundException, PlaceParentNotFoundException {
		logger.debug("Entered [modifyPlaceParent] of [PlaceServiceImpl]");
		
		if (placeId == 0 || parentPlaceId == 0) {
			logger.warn("Illegal data for changing place parent");
			throw new IllegalArgumentException("Illegal data for changing place parent");
		}
		
		PlaceTO modifiedPlace = placeDAO.modifyPlaceParent(placeId, parentPlaceId);
		
		logger.debug("Exiting [modifyPlaceParent] of [PlaceServiceImpl]");
		
		return modifiedPlace;
	}
	
	/**
	 * Method to modify a place parent
	 * 
	 * @param placeCode
	 * @param parentPlaceId
	 * @return PlaceTO
	 * @throws PlaceNotFoundException
	 * @throws PlaceParentNotFoundException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public PlaceTO modifyPlaceParent(String placeCode, int parentPlaceId) throws PlaceNotFoundException, PlaceParentNotFoundException {
		logger.debug("Entered [modifyPlaceParent] of [PlaceServiceImpl]");
		
		if (parentPlaceId == 0 || StringUtils.isNullOrEmpty(placeCode)) {
			logger.warn("Illegal data for changing place parent");
			throw new IllegalArgumentException("Illegal data for changing place parent");
		}
		
		PlaceTO childPlace = new PlaceTO();
		childPlace.setPlaceCode(placeCode);
		
		PlaceTO parentPlace = new PlaceTO();
		parentPlace.setPlaceId(parentPlaceId);
		
		PlaceTO modifiedPlace = placeDAO.modifyPlaceParent(childPlace, parentPlace);
		
		logger.debug("Exiting [modifyPlaceParent] of [PlaceServiceImpl]");
		
		return modifiedPlace;
	}
	
	/**
	 * Method to modify a place parent
	 * 
	 * @param placeId
	 * @param parentPlaceCode
	 * @return PlaceTO
	 * @throws PlaceNotFoundException
	 * @throws PlaceParentNotFoundException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public PlaceTO modifyPlaceParent(int placeId, String parentPlaceCode) throws PlaceNotFoundException, PlaceParentNotFoundException {
		logger.debug("Entered [modifyPlaceParent] of [PlaceServiceImpl]");
		
		if (placeId == 0 || StringUtils.isNullOrEmpty(parentPlaceCode)) {
			logger.warn("Illegal data for changing place parent");
			throw new IllegalArgumentException("Illegal data for changing place parent");
		}
		
		PlaceTO childPlace = new PlaceTO();
		childPlace.setPlaceId(placeId);
		
		PlaceTO parentPlace = new PlaceTO();
		parentPlace.setPlaceCode(parentPlaceCode);
		
		PlaceTO modifiedPlace = placeDAO.modifyPlaceParent(childPlace, parentPlace);
		
		logger.debug("Exiting [modifyPlaceParent] of [PlaceServiceImpl]");
		
		return modifiedPlace;
	}
	
	/**
	 * Method to modify a place parent
	 * 
	 * @param placeCode
	 * @param parentPlaceCode
	 * @return PlaceTO
	 * @throws PlaceNotFoundException
	 * @throws PlaceParentNotFoundException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public PlaceTO modifyPlaceParent(String placeCode, String parentPlaceCode) throws PlaceNotFoundException, PlaceParentNotFoundException {
		logger.debug("Entered [modifyPlaceParent] of [PlaceServiceImpl]");
		
		if (StringUtils.isNullOrEmpty(placeCode) || StringUtils.isNullOrEmpty(parentPlaceCode)) {
			logger.warn("Illegal data for changing place parent");
			throw new IllegalArgumentException("Illegal data for changing place parent");
		}
		
		PlaceTO childPlace = new PlaceTO();
		childPlace.setPlaceCode(placeCode);
		
		PlaceTO parentPlace = new PlaceTO();
		parentPlace.setPlaceCode(parentPlaceCode);
		
		PlaceTO modifiedPlace = placeDAO.modifyPlaceParent(childPlace, parentPlace);
		
		logger.debug("Exiting [modifyPlaceParent] of [PlaceServiceImpl]");
		
		return modifiedPlace;
	}
	
	/**
	 * Method to remove a place
	 * 
	 * @param placeId
	 * @return boolean
	 * @throws PlaceNotFoundException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public void removePlace(int placeId) throws PlaceNotFoundException {
		logger.debug("Entered [removePlace] of [PlaceServiceImpl]");
		
		if (placeId == 0) {
			logger.warn("Illegal place id : " + placeId);
			throw new IllegalArgumentException("Illegal place id : " + placeId);
		}
		
		placeDAO.removePlace(placeId);
		logger.debug("Exiting [removePlace] of [PlaceServiceImpl]");
	}
	
	/**
	 * Method to remove a place
	 * 
	 * @param placeCode
	 * @return boolean
	 * @throws PlaceNotFoundException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public void removePlace(String placeCode) throws PlaceNotFoundException {
		logger.debug("Entered [removePlace] of [PlaceServiceImpl]");
		
		if (StringUtils.isNullOrEmpty(placeCode)) {
			logger.warn("Illegal Place Code");
			throw new IllegalArgumentException("Illegal Place Code");
		}
		
		PlaceTO placeTO = new PlaceTO();
		placeTO.setPlaceCode(placeCode);
		
		placeDAO.removePlace(placeTO);
		
		logger.debug("Exiting [removePlace] of [PlaceServiceImpl]");
	}
	
	/**
	 * Method to get child places till the specified category like states in India, districts in India e.t.c
	 *  
	 * @param toCategoryId
	 * @param placeId
	 * @return List<PlaceTO>
	 * @throws PlaceNotFoundException
	 * @throws CategoryNotFoundException
	 */
	@Override
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public List<PlaceTO> getPlaces(int toCategoryId, int placeId) throws PlaceNotFoundException, CategoryNotFoundException {
		logger.debug("Entered [getPlaces] of [PlaceServiceImpl]");
		
		if (toCategoryId == 0 || placeId == 0) {
			logger.warn("Illegal arguments for getting places");
			throw new IllegalArgumentException("Illegal arguments for getting places");
		}
		
		PlaceTO placeTO = new PlaceTO();
		placeTO.setPlaceId(placeId);
		
		CategoryTO categoryTO = new CategoryTO();
		categoryTO.setCategoryId(toCategoryId);
		
		List<PlaceTO> places = placeDAO.getPlaces(placeTO, categoryTO);
		logger.debug("Exiting [getPlaces] of [PlaceServiceImpl]");
		
		return places;
	}
	
	/**
	 * Method to get child places till the specified category like states in India, districts in India e.t.c
	 * 
	 * @param toCategoryName
	 * @param placeId
	 * @return List<PlaceTO>
	 * @throws PlaceNotFoundException
	 * @throws CategoryNotFoundException
	 */
	@Override
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public List<PlaceTO> getPlaces(String toCategoryName, int placeId) throws PlaceNotFoundException, CategoryNotFoundException {
		logger.debug("Entered [getPlaces] of [PlaceServiceImpl]");
		
		if (StringUtils.isNullOrEmpty(toCategoryName) || placeId == 0) {
			logger.warn("Illegal arguments for getting places");
			throw new IllegalArgumentException("Illegal arguments for getting places");
		}
		
		PlaceTO placeTO = new PlaceTO();
		placeTO.setPlaceId(placeId);
		
		CategoryTO categoryTO = new CategoryTO();
		categoryTO.setCategoryName(toCategoryName);
		
		List<PlaceTO> places = placeDAO.getPlaces(placeTO, categoryTO);
		
		logger.debug("Exiting [getPlaces] of [PlaceServiceImpl]");
		
		return places;
	}
	
	/**
	 * Method to get child places till the specified category like states in India, districts in India e.t.c
	 * 
	 * @param toCategoryId
	 * @param placeCode
	 * @return List<PlaceTO>
	 * @throws PlaceNotFoundException
	 * @throws CategoryNotFoundException
	 */
	@Override
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public List<PlaceTO> getPlaces(int toCategoryId, String placeCode) throws PlaceNotFoundException, CategoryNotFoundException {
		logger.debug("Entered [getPlaces] of [PlaceServiceImpl]");
		
		if (toCategoryId == 0 || StringUtils.isNullOrEmpty(placeCode)) {
			logger.warn("Illegal arguments for getting places");
			throw new IllegalArgumentException("Illegal arguments for getting places");
		}
		
		PlaceTO placeTO = new PlaceTO();
		placeTO.setPlaceCode(placeCode);
		
		CategoryTO categoryTO = new CategoryTO();
		categoryTO.setCategoryId(toCategoryId);
		
		List<PlaceTO> places = placeDAO.getPlaces(placeTO, categoryTO);
		logger.debug("Exiting [getPlaces] of [PlaceServiceImpl]");
		
		return places;
	}
	
	/**
	 * Method to get child places till the specified category like states in India, districts in India e.t.c
	 * 
	 * @param toCategoryName
	 * @param placeCode
	 * @return List<PlaceTO>
	 * @throws PlaceNotFoundException
	 * @throws CategoryNotFoundException
	 */
	@Override
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public List<PlaceTO> getPlaces(String toCategoryName, String placeCode) throws PlaceNotFoundException, CategoryNotFoundException {
		logger.debug("Entered [getPlaces] of [PlaceServiceImpl]");
		
		if (StringUtils.isNullOrEmpty(toCategoryName) || StringUtils.isNullOrEmpty(placeCode)) {
			logger.warn("Illegal arguments for getting places");
			throw new IllegalArgumentException("Illegal arguments for getting places");
		}
		
		PlaceTO placeTO = new PlaceTO();
		placeTO.setPlaceCode(placeCode);
		
		CategoryTO categoryTO = new CategoryTO();
		categoryTO.setCategoryName(toCategoryName);
		
		List<PlaceTO> places = placeDAO.getPlaces(placeTO, categoryTO);
		logger.debug("Exiting [getPlaces] of [PlaceServiceImpl]");
		
		return places;
	}
	
	/**
	 * Method to get child places of a specified parent place
	 * 
	 * @param placeCode
	 * @return List<PlaceTO>
	 * @throws PlaceNotFoundException
	 */
	@Override
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public List<PlaceTO> getPlaces(String placeCode) throws PlaceNotFoundException {
		// TODO Auto-generated method stub
		
		logger.debug("Entered [getPlaces] of [PlaceServiceImpl]");
		
		if (StringUtils.isNullOrEmpty(placeCode)) {
			logger.warn("Illegal arguments for getting places");
			throw new IllegalArgumentException("Illegal arguments for getting places");
		}
		
		logger.debug("Exiting [getPlaces] of [PlaceServiceImpl]");
		throw new UnsupportedOperationException();
	}
	
	/**
	 * Method to get child places of a specified parent place
	 * 
	 * @param placeId
	 * @return List<PlaceTO>
	 * @throws PlaceNotFoundException
	 */
	@Override
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public List<PlaceTO> getPlaces(int placeId) throws PlaceNotFoundException {
		// TODO Auto-generated method stub
		
		logger.debug("Entered [getPlaces] of [PlaceServiceImpl]");
		
		if (placeId == 0) {
			logger.warn("Illegal arguments for getting places");
			throw new IllegalArgumentException("Illegal arguments for getting places");
		}
		logger.debug("Exiting [getPlaces] of [PlaceServiceImpl]");
		throw new UnsupportedOperationException();
	}
	
	/**
	 * Method to get all places of specified category
	 * 
	 * @param categoryName
	 * @return List<PlaceTO>
	 * @throws CategoryNotFoundException
	 */
	@Override
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public List<PlaceTO> getPlacesOfCategory(String categoryName) throws CategoryNotFoundException {
		// TODO Auto-generated method stub
		
		logger.debug("Entered [getPlaces] of [PlaceServiceImpl]");
		
		if (StringUtils.isNullOrEmpty(categoryName)) {
			logger.warn("Illegal arguments for getting places");
			throw new IllegalArgumentException("Illegal arguments for getting places");
		}
		logger.debug("Exiting [getPlaces] of [PlaceServiceImpl]");
		throw new UnsupportedOperationException();
	}
	
	/**
	 * Method to get all places of specified category
	 * 
	 * @param categoryId
	 * @return List<PlaceTO>
	 * @throws CategoryNotFoundException
	 */
	@Override
	@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
	public List<PlaceTO> getPlacesOfCategory(int categoryId) throws CategoryNotFoundException {
		// TODO Auto-generated method stub
		
		logger.debug("Entered [getPlaces] of [PlaceServiceImpl]");
		
		if (categoryId == 0) {
			logger.warn("Illegal arguments for getting places");
			throw new IllegalArgumentException("Illegal arguments for getting places");
		}		
		
		logger.debug("Exiting [getPlaces] of [PlaceServiceImpl]");
		
		throw new UnsupportedOperationException();		
	}	
	
}